﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Networker.cs" company="HelloWorld">
//   BY苏宣
// </copyright>
// <summary>
//   Defines the Networker type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace WindowsFormsApp2.Service
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net;
    using System.Text;

    using Newtonsoft.Json.Linq;

    using RestSharp;

    /// <summary>
    /// The networker.
    /// </summary>
    public class Networker
    {
        /// <summary>
        /// The root path.
        /// </summary>
        private readonly string rootPath;

        /// <summary>
        /// Initializes a new instance of the <see cref="Networker"/> class. 
        /// </summary>
        /// <param name="rootPath">
        /// 传入根目录的绝对地址
        /// </param>
        public Networker(string rootPath)
        {
            this.rootPath = rootPath;
        }

                /// <summary>
        /// The http API.
        /// </summary>
        /// <param name="url">
        /// The url.
        /// </param>
        /// <param name="jsonstr">
        /// The JSON String.
        /// </param>
        /// <param name="type">
        /// The type.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string HttpApi(string url, string jsonstr, string type)
        {
            try
            {
                var encoding = Encoding.UTF8;
                var request = (HttpWebRequest)WebRequest.Create(url);
                request.Accept = "text/html,application/xhtml+xml,*/*";
                request.ContentType = "application/json";
                request.Method = type.ToUpper();
                if (type == "post")
                {
                    var buffer = encoding.GetBytes(jsonstr);
                    request.ContentLength = buffer.Length;
                    request.GetRequestStream().Write(buffer, 0, buffer.Length);
                }

                var response = (HttpWebResponse)request.GetResponse();
                using (var reader = new StreamReader(
                    response.GetResponseStream() ?? throw new InvalidOperationException(),
                    Encoding.UTF8))
                {
                    return reader.ReadToEnd();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

            return string.Empty;
        }

        /// <summary>
        /// The compare list.
        /// </summary>
        /// <param name="local">
        /// The local.
        /// </param>
        /// <param name="online">
        /// The online.
        /// </param>
        /// <returns>
        /// The <see>
        ///     <cref>Dictionary</cref>
        /// </see>
        /// .
        /// </returns>
        public static Dictionary<string, List<string>> CompareList(List<string> local, List<string> online)
        {
            var localLack = online.FindAll(file => !local.Contains(file));
            var onlineLack = local.FindAll(file => !online.Contains(file));
            var result =
                new Dictionary<string, List<string>> { { "undownload", localLack }, { "unupload", onlineLack } };
            return result;
        }

        /// <summary>
        /// The bytes 2 file.
        /// </summary>
        /// <param name="data">
        /// The data.
        /// </param>
        /// <param name="filename">
        /// The filename.
        /// </param>
        public static void Bytes2File(byte[] data, string filename)
        {
            using (var fs = new FileStream(filename, FileMode.Create))
            {
                try
                {
                    fs.Write(data, 0, data.Length);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }
        }

        /// <summary>
        /// 比对差异，下载和上传
        /// </summary>
        /// <param name="target">目标文件夹</param>
        /// <param name="localFiles">本地文件列表</param>
        public void CheckList(string target, List<string> localFiles)
        {
            try
            {
                // 目标地址
                const string Url = "http://101.201.249.192:8081/detail/";

                // 获取文件列表
                var getJson = HttpApi(Url + target, "{}", "get");

                // 解析
                var array = JArray.Parse(getJson);
                var onlineFiles = array.ToObject<List<string>>();

                // 比较差异
                var compare = CompareList(localFiles, onlineFiles);

                // 下载上传
                this.Download(target, compare["undownload"]);
                this.Upload(target, compare["unupload"]);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }

        /// <summary>
        /// The upload.
        /// </summary>
        /// <param name="target">
        /// The target.
        /// </param>
        /// <param name="flies">
        /// The up files.
        /// </param>
        public void Upload(string target, List<string> flies)
        {
            foreach (var file in flies)
            {
                var client = new RestClient("http://101.201.249.192:8081/upload") { Timeout = -1 };
                var request = new RestRequest(Method.POST);
                request.AddParameter("directory", target);
                request.AddFile("fileUpload", this.rootPath + "\\" + target + "\\公共\\" + file);
                var response = client.Execute(request);
                Console.WriteLine(response.Content);
            }            
        }

        /// <summary>
        /// The download.
        /// </summary>
        /// <param name="target">
        /// The target.
        /// </param>
        /// <param name="downFiles">
        /// The down files.
        /// </param>
        public void Download(string target, List<string> downFiles)
        {
            foreach (var file in downFiles)
            {
                var client = new RestClient($"http://101.201.249.192:8081/download/{target}/{file}") { Timeout = -1 };
                var request = new RestRequest(Method.GET);
                var response = client.DownloadData(request);
                Bytes2File(response, this.rootPath + "/" + target + "/公共/" + file);
            }
        }
    }
}
